﻿#include"XQAlgorithm.h"
#include<QFile>
#include<QRegExp>
#include<QFileInfoList>
#include<QDir>
#include<QEventLoop>
#include<QTimer>
#include<QJsonDocument>
#include<QJsonArray>
#include<QDebug>
#include<QtZlib/zlib.h>

bool isQNULL(const void* args, const char* argsName, const char* str, const char* funcName, const char* filePath, int line)
{
    if (args == NULL)
    {
        qInfo()<<QString().asprintf("%s\n参数:%s是NULL\t函数名:%s\n文件路径:%s\n正在编译文件的行号:%d\n", str, argsName, funcName, filePath, line);
        return true;
    }
    return false;
}
void deleteDirectory(const QString& dirPath)
{
    QFileInfoList fileList = QDir(dirPath).entryInfoList(QDir::NoDotAndDotDot | QDir::Files);
    for(auto& fileInfo: fileList) {
        QFile::remove(fileInfo.filePath());
    }

    QFileInfoList dirList = QDir(dirPath).entryInfoList(QDir::NoDotAndDotDot | QDir::Dirs);
    for(auto& dirInfo: dirList) {
        deleteDirectory(dirInfo.absoluteFilePath());
    }

    QDir().rmdir(dirPath);
}
bool moveDir(const QString& srcPath, const QString& dstPath)
{
    QDir sourceDir(srcPath);
    QDir destDir(dstPath);
    QDir dir; dir.mkpath(dstPath);
    if (!destDir.exists()) {
        if (!destDir.mkdir(dstPath)) {
            qWarning() << "Cannot create directory: " << dstPath;
            return false;
        }
    }

    QFileInfoList files = sourceDir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
    for (int i = 0; i < files.size(); ++i) {
        QFileInfo fileInfo = files.at(i);
        QString fileName = fileInfo.fileName();
        if (fileInfo.isFile()) {
            destDir.rename(fileInfo.absoluteFilePath(), destDir.absolutePath() + "/" + fileName);
        }
        else if (fileInfo.isDir()) {
            if (!destDir.mkdir(fileName)) {
                qWarning() << "Cannot create directory: " << destDir.absolutePath() + "/" + fileName;
                return false;
            }
            if (!moveDir(fileInfo.absoluteFilePath(), destDir.absolutePath() + "/" + fileName)) {
                return false;
            }
        }
    }

    sourceDir.rmdir(srcPath);
    return true;
}
// 文件大小转换成可读的字符串，后加B,KB,....
QString readableFileSize(quint64 filesize)
{
    QStringList units;
    units << "B" << "KB" << "MB" << "GB" << "TB" << "PB";
    double mod = 1024.0;
    double size = filesize;
    //qDebug() << size;
    int i = 0;
    long rest = 0;
    while (size >= mod && i < units.count() - 1)
    {
        rest = (long)size % (long)mod;
        size /= mod;
        i++;
    }
    QString szResult = QString::number(floor(size));
    if (rest > 0)
    {
        szResult += QString(".") + QString::number(rest).left(2);
    }
    szResult += units[i];
    return  szResult;
}
void setCssFile(QWidget* widget, const QString& css)
{
    if (widget == nullptr)
        return;
    // 从文件中加载样式表
  QFile file(css);
  file.open(QFile::ReadOnly | QFile::Text);
  QString stylesheet = file.readAll();
  file.close();

  // 设置样式表
  widget->setStyleSheet(stylesheet);
}

bool RegexMatch(const QString& test, const QString& pattern)
{
    // 创建 QRegExp 对象，并设置模式字符串和匹配选项
    QRegExp rx(pattern);
    //rx.setCaseSensitivity(Qt::CaseInsensitive);  // 不区分大小写
    // 进行正则表达式匹配，并输出结果
    return rx.exactMatch(test);
}

QStringList strtok(const QString& Text, const QString& Delimiter, const bool space)
{
    QStringList list;
    size_t size = Text.size();
    size_t start = 0;
    size_t nSel = 0;
    //qInfo() << Text;
    do
    {
        nSel = Text.indexOf(Delimiter, start);
        if (nSel == -1)//没找到
        {
           break;
        }
        if (nSel == start )
        {
            if(space)
                list << QString();
        }
        else
        {
            list << Text.mid(start, nSel - start);
        }
        start = nSel + Delimiter.size();
    } while (start < size);
    if(size > start)
    {
        list << Text.mid(start);
    }
    return std::move(list);
}

void centerShow(QWidget* showWidget, QWidget* refer)
{
    if (showWidget == nullptr || refer == nullptr)
        return;
    //置顶窗口判断
    if (refer->windowFlags() & Qt::WindowStaysOnTopHint)
        showWidget->setWindowFlag(Qt::WindowStaysOnTopHint);
    else
        showWidget->setWindowFlag(Qt::WindowStaysOnTopHint,false);
    //窗口显示
    showWidget->show();
    size_t w = showWidget->width(), h = showWidget->height();
    QPoint pos = refer->mapToGlobal(QPoint(0, 0)) - (QPoint(w - refer->width(), h - refer->height()) / 2);
    if(pos.x()>0&&pos.y()>0)
        showWidget->move(pos);//移动新窗口居中显示
    //居中显示
    showWidget->activateWindow();
}

void XQDelayEventLoop(qint64 msec)
{
    // 创建一个事件循环对象
    QEventLoop Loop;
    // 创建一个定时器
    QTimer timer;
    timer.setInterval(msec); 
    timer.setSingleShot(true); // 只触发一次
    // 连接定时器的超时信号到事件循环的退出槽函数
    QObject::connect(&timer, &QTimer::timeout, &Loop, &QEventLoop::quit);
    timer.start();
    // 启动事件循环
    Loop.exec();
}

QJsonObject variantMap_toJsonObject(const QVariantMap& map)
{
    return QJsonObject::fromVariantMap(map);
}

QByteArray variantMap_toJson(const QVariantMap& map)
{
    return QJsonDocument(QJsonObject::fromVariantMap(map)).toJson();
}

QJsonObject variantList_toJsonObject(const QVariantList& list)
{
    QJsonArray jsonArray;
    for (const QVariant& variant : list) {
        jsonArray.append(QJsonValue::fromVariant(variant));
    }
    return QJsonDocument(jsonArray).object();
}

QByteArray variantList_toJson(const QVariantList& list)
{
    return QJsonDocument(variantList_toJsonObject(list)).toJson();
}

QByteArray gzipCompress(const QByteArray& data, int leve, int BufferSize)
{
    if (data.isEmpty() || BufferSize < 10)
        return QByteArray();
    QByteArray outBuf;
    z_stream c_stream;
    int err = 0;
    int windowBits = 15;
    int GZIP_ENCODING = 16;
    if (!data.isEmpty())
    {
        c_stream.zalloc = (alloc_func)0;
        c_stream.zfree = (free_func)0;
        c_stream.opaque = (voidpf)0;
        c_stream.next_in = (Bytef*)data.data();
        c_stream.avail_in = data.size();
        if (deflateInit2(&c_stream, leve, Z_DEFLATED,
            MAX_WBITS + GZIP_ENCODING, 8, Z_DEFAULT_STRATEGY) != Z_OK) return QByteArray();
        auto buffer = new char[BufferSize] {0};
        for (;;) {
           /* char [BufferSize] = { 0 };*/
            c_stream.next_out = (Bytef*)buffer;
            c_stream.avail_out = BufferSize;
            int err = deflate(&c_stream, Z_FINISH);
            outBuf.append(buffer, BufferSize - c_stream.avail_out);
            if (err == Z_STREAM_END || err != Z_OK)
            {
                break;
            }
        }
        auto total = c_stream.total_out;
        deflateEnd(&c_stream);
        total = c_stream.total_out;
        delete[] buffer;
    }
    return outBuf;
}

QByteArray gzipUnCompress(const QByteArray& data, int BufferSize)
{
    if (data.isEmpty() || BufferSize < 10)
        return QByteArray();
    QByteArray outBuffer;
    z_stream strm;
    strm.zalloc = NULL;
    strm.zfree = NULL;
    strm.opaque = NULL;

    strm.avail_in = data.size();
    strm.next_in = (Bytef*)data.data();

    int err = -1, ret = -1;
    err = inflateInit2(&strm, MAX_WBITS + 16);
    auto buffer = new char[BufferSize] {0};
    if (err == Z_OK) {
        while (true)
        {
            //char buffer[BufferSize] = { 0 };
            strm.avail_out = BufferSize;
            strm.next_out = (Bytef*)buffer;
            int code = inflate(&strm, Z_FINISH);
            outBuffer.append(buffer, BufferSize - strm.avail_out);
            if (Z_STREAM_END == code)
            {
                break;
            }
        }
    }
    inflateEnd(&strm);
    delete[] buffer;
    return outBuffer;
 
}

QByteArray deflateCompress(const QByteArray& data, int leve)
{
    //// 压缩后的数据缓冲区
    auto compressed_data=new unsigned char[data.size()];
    uLongf compressed_size = data.size();
    QByteArray out;
    do {
        // 使用 zlib 进行压缩
        int result = compress2(compressed_data, &compressed_size, (const Bytef*)data.data(), data.size(), leve);
        if (result == Z_OK) {
            // 压缩成功，输出数据
            out.append((char*)compressed_data, compressed_size);
            break;
        }
        else if (result == Z_BUF_ERROR) {
            // 内存不足，扩展缓冲区大小
            delete[] compressed_data;
            compressed_size *= 2;
            compressed_data = new Bytef[compressed_size];
        }
        else {
            break;
        }
    } while (true);

    delete[] compressed_data;
    return out;
}

QByteArray deflateUnCompress(const QByteArray& data)
{
    // 解压缩后的数据缓冲区
    uLongf uncompressed_size = data.size()*3;
    Bytef* uncompressed_data = new Bytef[uncompressed_size];
    QByteArray out;
    int result = Z_OK;
    do {
        // 使用 zlib 进行解压缩
        result = uncompress(uncompressed_data, &uncompressed_size, (Bytef*)data.data(), data.size());
        if (result == Z_OK) {
            // 解压缩成功，输出数据
            out.append((char*)uncompressed_data, uncompressed_size);
            break;
        }
        else if (result == Z_BUF_ERROR) {
            // 内存不足，扩展缓冲区大小
            delete[] uncompressed_data;
            uncompressed_size *= 2;
            uncompressed_data = new Bytef[uncompressed_size];
        }
        else {
            //std::cerr << "Decompression failed with error code: " << result << std::endl;
            break;
        }
    } while (true);

    // 释放内存
    delete[] uncompressed_data;
    return out;
}
